// JAY SHREE RAM!!
#include<bits/stdc++.h>
using namespace std;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
//using namespace __gnu_pbds;
#define int long long int
#define cy cout << "YES" << endl
#define cn cout << "NO" << endl
#define c1 cout << "-1" << endl
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define maxi *max_element
#define mini *min_element
#define pb push_back
#define sz(x) (int)((x).size())
#define ff first
#define ss second
#define MOD 1000000007
//#const int inf 1e18+1
#define vi vector<int>
#define input(v) for(auto &item : v) cin >> item;
#define mod_add(a, b, m) (((a + b) % m) + m) % m
#define mod_mul(a, b, m) (((a * b) % m) + m) % m
#define mod_sub(a, b, m) (((a - b) % m) + m) % m
////#define ordered_set tree<int, null_type, less<int>,
// ---------------------------------------------------------------------------------------
bool cmp(pair<int,int> a, pair<int,int> b) {
if (a.first > b.first) {
return true;
} else if (a.first < b.first) {
return false;
} else {
return a.second < b.second;
}
}
bool isPrime(int n) {
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
vi sieve(int n) {
vi prime;
vi vis(n + 1, 1);
vis[0] = vis[1] = 0;
for (int i = 2; i * i <= n; i++) {
if (vis[i]) {
for (int j = i * i; j <= n; j += i) {
vis[j] = 0;
}
}
}
for (int i = 2; i <= n; i++) {
if (vis[i]) {
prime.pb(i);
}
}
return prime;
}
int BinExp(int a, int b, int m) {
int ans = 1;
while (b > 0) {
if (b & 1) {
ans = (ans * 1LL * a) % m;
}
a = (a * 1LL * a) % m;
b >>= 1;
}
return ans;
}
// ----------------------------------------------------------------------------------------
void solve() {
// Your solution code goes here
int n,m,q;
cin>>n>>m>>q;
vector<vector<int>> arr(n,vector<int> (m,0));
/* for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
arr[i][j]=0;
}
}
*/
class Operation
{
public:
int type;
int row,col;
int val;
Operation(int t,int r,int c,int v)
{
type=t;
row=r;
col=c;
val=v;
}
};
vector<Operation> oper;
while(q--)
{
int type;
cin>>type;
if(type==1)
{
int r;cin>>r;
oper.pb({type,r-1,0,0});
}
else if(type==2)
{
int c;cin>>c;
oper.pb({type,0,c-1,0});
}
else
{
int r,c,x;
cin>>r>>c>>x;
oper.pb({type,r-1,c-1,x});
}
}
// q-1 se bhi kar sakte.. but while loop ke baad q would exhaust soo..
for(int i=sz(oper)-1;i>=0;i--)
{
Operation op=oper[i];
if(op.type==1)
{
int temp=arr[op.row][m-1];
// last ele ko store kiya
for(int j=m-1;j>0;j--)
{
arr[op.row][j]=arr[op.row][j-1];
}
arr[op.row][0]=temp; // first banane ke liye
// de circular shift xd
}
else if(op.type==2)
{
int temp=arr[n-1][op.col];
for(int j=n-1;j>0;j--)
{
arr[j][op.col]=arr[j-1][op.col];
}
arr[0][op.col]=temp;
}
else
{
arr[op.row][op.col]=op.val;
}
}
for(auto &it : arr)
{
for(auto & it1: it)
{
cout<<it1<<" ";
}
cout<<endl;
}
}
int32_t main() {
int t=1; //cin >> t;
while (t--) {
solve();
}
return 0;
}
791A - Bear and Big Brother | 1452A - Robot Program |
344A - Magnets | 96A - Football |
702B - Powers of Two | 1036A - Function Height |
443A - Anton and Letters | 1478B - Nezzar and Lucky Number |
228A - Is your horseshoe on the other hoof | 122A - Lucky Division |
1611C - Polycarp Recovers the Permutation | 432A - Choosing Teams |
758A - Holiday Of Equality | 1650C - Weight of the System of Nested Segments |
1097A - Gennady and a Card Game | 248A - Cupboards |
1641A - Great Sequence | 1537A - Arithmetic Array |
1370A - Maximum GCD | 149A - Business trip |
34A - Reconnaissance 2 | 59A - Word |
462B - Appleman and Card Game | 1560C - Infinity Table |
1605C - Dominant Character | 1399A - Remove Smallest |
208A - Dubstep | 1581A - CQXYM Count Permutations |
337A - Puzzles | 495A - Digital Counter |